#******************************************************************************
#******************************************************************************

# import libraries

#from src.hyhetra.common.fluids import Fluid, FluidDatabase

from src.hyhetra.pipes.classes import StandardisedPipeDatabase, InsulatedPipe

from src.hyhetra.pipes.classes import StandardisedPipe, Pipe

from src.hyhetra.pipes.twin import StandardisedTwinPipe, InsulatedTwinPipe

# import src.hyhetra.geometry.pipes as hht

import numpy as np

import numbers

#******************************************************************************
#******************************************************************************

def examples(singlepipedb: StandardisedPipeDatabase,
             twinpipedb: StandardisedPipeDatabase):
    
    # # single pipe data files
    
    # singlepipedata_files = ['data/pipes/singlepipes_s1.csv',
    #                         'data/pipes/singlepipes_s2.csv',
    #                         'data/pipes/singlepipes_s3.csv']
    
    # # twin pipe data files
    
    # twinpipedata_files = ['data/pipes/twinpipes_s1.csv',
    #                       'data/pipes/twinpipes_s2.csv',
    #                       'data/pipes/twinpipes_s3.csv']
    

    # singlepipedb = StandardisedPipeDatabase(source=singlepipedata_files)

    # twinpipedb = StandardisedPipeDatabase(source=twinpipedata_files)
    
    #**************************************************************************
    #**************************************************************************
    
    # carry out tests
    
    example_pipe_obj_creation_direct()
    
    example_ins_pipe_obj_creation_direct()
    
    example_stdpipeobj_creation_direct()
    
    example_ins_twin_pipe_obj_creation_direct()
    
    example_stdtwinpipeobj_creation_direct()
    
    #**************************************************************************
    #**************************************************************************
    
    verify_pipedatabase(singlepipedb)
    
    example_stdpipeobj_creation_viadb(singlepipedb)
    
    example_stdtwinpipeobj_creation_viadb(twinpipedb)

#******************************************************************************
#******************************************************************************

# check regular pipe object

def verify_pipe_obj(pipe):
    
    # check if it has ....
        
    assert hasattr(pipe, "d_int")
    
    assert hasattr(pipe, "d_ext")
    
    assert hasattr(pipe, "k")
    
    assert hasattr(pipe, "e_eff")
    
    assert hasattr(pipe, "length")
    
    # check attribute types
    
    assert isinstance(pipe.d_int, numbers.Real)
    
    assert pipe.d_int > 0
    
    assert isinstance(pipe.d_ext, numbers.Real)
    
    assert pipe.d_ext > 0
    
    assert isinstance(pipe.d_int, numbers.Real)
    
    assert pipe.d_int > 0
    
    assert isinstance(pipe.k, numbers.Real)
    
    assert pipe.k > 0
    
    assert isinstance(pipe.e_eff, numbers.Real)
    
    assert pipe.e_eff >= 0
    
    assert isinstance(pipe.length, numbers.Real)
    
    assert pipe.length > 0
    
    # the pipe dimensions must make sense
    
    assert pipe.d_int <= pipe.d_ext

#******************************************************************************
#******************************************************************************

# check insulated pipe object

def verify_ins_pipe_obj(pipe):
    
    # test mother class compliance
    
    verify_pipe_obj(pipe)
    
    # check if it has ....
    
    assert hasattr(pipe, "d_ins")
    
    assert hasattr(pipe, "d_cas")
    
    assert hasattr(pipe, "k_ins")
    
    assert hasattr(pipe, "k_cas")
    
    # check attribute types
    
    assert isinstance(pipe.d_ins, numbers.Real)
    
    assert pipe.d_ins > 0
    
    assert isinstance(pipe.d_cas, numbers.Real)
    
    assert pipe.d_cas > 0
    
    assert isinstance(pipe.k_ins, numbers.Real)
    
    assert pipe.k_ins > 0
    
    assert isinstance(pipe.k_cas, numbers.Real)
    
    assert pipe.k_cas > 0
    
    # the pipe dimensions must make sense
    
    assert pipe.d_ext <= pipe.d_ins
        
    assert pipe.d_ins <= pipe.d_cas

#******************************************************************************
#******************************************************************************

# check standardised pipe

def verify_std_pipe(pipe):
    
    # test mother class compliance
    
    verify_ins_pipe_obj(pipe)
    
    # check if it has ....
    
    assert hasattr(pipe, "sp")
    
    assert hasattr(pipe, "p_rated")
    
    assert hasattr(pipe, "e_rel")
    
    #assert hasattr(pipe, "make_ref")
    
    # check attribute types
    
    assert isinstance(pipe.sp, numbers.Real)
    
    assert pipe.sp >= 0
    
    assert isinstance(pipe.p_rated, numbers.Real)
    
    assert pipe.p_rated > 0
    
    assert isinstance(pipe.e_rel, numbers.Real)
    
    assert pipe.e_rel >= 0
    
    assert isinstance(pipe.length, numbers.Real)
    
    assert pipe.length > 0
    
    #assert type(pipe.make_ref) == tuple

#******************************************************************************
#******************************************************************************

# test pipe database creation

def verify_pipedatabase(pipedb):
    
    # check if attributes exist
    
    assert hasattr(pipedb, "pipe_tuples")
    
    assert hasattr(pipedb, "d_int")
    
    assert hasattr(pipedb, "d_ext")
    
    assert hasattr(pipedb, "d_ins")
    
    assert hasattr(pipedb, "d_cas")
    
    assert hasattr(pipedb, "k_pipe")
    
    assert hasattr(pipedb, "k_ins")
    
    assert hasattr(pipedb, "k_cas")
    
    assert hasattr(pipedb, "sp")
    
    assert hasattr(pipedb, "length")
    
    assert hasattr(pipedb, "p_rated")
    
    assert hasattr(pipedb, "e_eff")
    
    assert hasattr(pipedb, "make_ref_tuples")
    
    assert hasattr(pipedb, "pipe_dist")
    
    # check attribute types
    
    assert type(pipedb.pipe_tuples) == list
    
    assert type(pipedb.d_int) == dict
    
    assert type(pipedb.d_ext) == dict
    
    assert type(pipedb.d_ins) == dict
    
    assert type(pipedb.d_cas) == dict
    
    assert type(pipedb.k_pipe) == dict
    
    assert type(pipedb.k_ins) == dict
    
    assert type(pipedb.k_cas) == dict
    
    assert type(pipedb.sp) == dict
    
    assert type(pipedb.length) == dict
    
    assert type(pipedb.p_rated) == dict
    
    assert type(pipedb.e_eff) == dict
    
    assert type(pipedb.make_ref_tuples) == dict
    
    assert type(pipedb.pipe_dist) == dict
    
    # check if there are elements for each key
    
    for tuple_entry in pipedb.pipe_tuples:
        
        # (dn,s,make,ref)
        
        assert pipedb.d_int[tuple_entry] != None
            
        assert pipedb.d_ext[tuple_entry] != None
            
        assert pipedb.d_ins[tuple_entry] != None
            
        assert pipedb.d_cas[tuple_entry] != None
            
        assert pipedb.k_pipe[tuple_entry] != None
            
        assert pipedb.k_ins[tuple_entry] != None
            
        assert pipedb.k_cas[tuple_entry] != None
            
        assert pipedb.sp[tuple_entry] != None
            
        assert pipedb.length[tuple_entry] != None
            
        assert pipedb.p_rated[tuple_entry] != None
            
        assert pipedb.e_eff[tuple_entry] != None
        
        # pipe_dist is only for twin pipes
            
        assert tuple_entry in pipedb.pipe_dist

#******************************************************************************
#******************************************************************************

# test creating standardisedpipe class instances using a pipe database

def example_stdpipeobj_creation_viadb(pipedb):
    
    # specify
    
    pipe_tuple = pipedb.pipe_tuples[0]
    
    pipe_specific_price = 3567
    
    pipe_length = 2015
    
    pipe_e_rel = 0.034
    
    #**************************************************************************
    
    # standardised pipe
    
    pipe = StandardisedPipe(
        sp=pipe_specific_price,
        length=pipe_length,
        pipe_tuple=pipe_tuple,
        e_rel=pipe_e_rel,
        db=pipedb)
    
    # verify pipe
    
    pipe.ValidateStandardisedPipe()
    
    # check for specific values
    
    assert pipe_specific_price == pipe.sp
    
    assert pipe_length == pipe.length
    
    assert pipe_e_rel == pipe.e_rel
    
    #**************************************************************************
    
    # standardised pipe
    
    pipe = StandardisedPipe(
        pipe_tuple=pipe_tuple,
        sp=pipe_specific_price,
        db=pipedb)
    
    # verify pipe
    
    pipe.ValidateStandardisedPipe()
    
    #**************************************************************************
    
    # direct method
    
    pipe_e_eff = 1e-3
    
    # standardised pipe
    
    pipe = StandardisedPipe(
        pipe_tuple=pipe_tuple,
        e_eff=pipe_e_eff,
        sp=pipe_specific_price,
        db=pipedb)
    
    # verify pipe
    
    pipe.ValidateStandardisedPipe()
    
    #**************************************************************************

#******************************************************************************
#******************************************************************************

# test creating standardisedtwinpipe class instances using a pipe database

def example_stdtwinpipeobj_creation_viadb(pipedb):
    
    # specify
    
    pipe_tuple = pipedb.pipe_tuples[0]
    
    pipe_specific_price = 3567
    
    pipe_length = 2015
    
    pipe_e_rel = 0.034
    
    #**************************************************************************
    
    # standardised pipe
    
    pipe = StandardisedTwinPipe(
        sp=pipe_specific_price,
        length=pipe_length,
        pipe_tuple=pipe_tuple,
        e_rel=pipe_e_rel,
        db=pipedb)
    
    # verify pipe
    
    pipe.ValidateStandardisedTwinPipe()
    
    # check for specific values
    
    assert pipe_specific_price == pipe.sp
    
    assert pipe_length == pipe.length
    
    assert pipe_e_rel == pipe.e_rel
    
    #**************************************************************************
    
    # standardised pipe
    
    pipe = StandardisedTwinPipe(
        sp=pipe_specific_price,
        pipe_tuple=pipe_tuple,
        db=pipedb)
    
    # verify pipe
    
    pipe.ValidateStandardisedTwinPipe()

#******************************************************************************
#******************************************************************************

# test creating standardisedpipe class instances manually

def example_stdpipeobj_creation_direct():
    
    pipe = StandardisedPipe(
        length=float(1000),
        e_eff=float(0),
        d_int=float(1),
        d_ext=float(2),
        d_ins=float(3),
        d_cas=float(4),
        k=float(5),
        k_ins=float(0.05),
        k_cas=float(0.5),
        p_rated=float(15),
        sp=float(0),
        #make_ref=('hey','ho'),
        )
    
    # verify pipe
    
    pipe.ValidateStandardisedPipe()
    
    #**************************************************************************
        
    pipe = StandardisedPipe(
        length=float(1000),
        e_rel=float(0),
        d_int=float(1),
        d_ext=float(2),
        d_ins=float(3),
        d_cas=float(4),
        k=float(5),
        k_ins=float(0.05),
        k_cas=float(0.5),
        p_rated=float(15),
        sp=float(0),
        #make_ref=('hey','ho'),
        )
    
    # verify pipe
    
    pipe.ValidateStandardisedPipe()
    
    #**************************************************************************

#******************************************************************************
#******************************************************************************

# test creating standardisedpipe class instances manually

def example_stdtwinpipeobj_creation_direct():
    
    pipe = StandardisedTwinPipe(
        length=float(1000),
        e_eff=float(0),
        d_int=float(0.25),
        d_ext=float(0.27),
        d_ins=float(1.8),
        d_cas=float(2.0),
        k=float(5),
        k_ins=float(0.05),
        k_cas=float(0.5),
        p_rated=float(15),
        sp=float(0),
        pipe_center_distance=float(0.6)
        #make_ref=('hey','ho'),
        )
    
    # verify pipe
    
    pipe.ValidateStandardisedTwinPipe()

#******************************************************************************
#******************************************************************************

# test creating pipe class instances using a pipe database

def example_pipe_obj_creation_direct():
    
    # create pipe obj
    
    pipe = Pipe(
        length=float(300),
        k=float(400),
        d_int=float(1.3),
        d_ext=float(1.5),
        e_eff=float(5e-3))
    
    # test object
    
    pipe.ValidatePipe()

#******************************************************************************
#******************************************************************************

# test creating standardisedpipe class instances using a pipe database

def example_ins_pipe_obj_creation_direct():
    
    # create object
            
    pipe = InsulatedPipe(
        length=1000,
        d_int=0.02,
        d_ext=0.022,
        d_ins=0.100,
        d_cas=0.105,
        e_eff=5e-3,
        k=50,
        k_ins=0.05,
        k_cas=0.5
        )
    
    # test object
    
    pipe.ValidateInsulatedPipe()

#******************************************************************************
#******************************************************************************

def example_ins_twin_pipe_obj_creation_direct():
    
    # create object
            
    pipe = InsulatedTwinPipe(
        length=1000,
        d_int=0.02,
        d_ext=0.022,
        d_ins=0.100,
        d_cas=0.105,
        e_eff=5e-3,
        k=50,
        k_ins=0.05,
        k_cas=0.5,
        pipe_center_distance=0.05
        )
    
    # test object
    
    pipe.ValidateInsulatedTwinPipe()

#******************************************************************************
#******************************************************************************